<?php
/**
 *+------------------
 * Lflow
 *+------------------
 * Copyright (c) 2023~2030 gitee.com/liu_guan_qing All rights reserved.本版权不可删除，侵权必究
 *+------------------
 * Author: Mr.April(405784684@qq.com)
 *+------------------
 */

namespace lflow\parser;

use lflow\ckpt\NodeCkpt;
use lflow\ckpt\TransitionCkpt;
use lflow\lib\util\Logger;
use lflow\lib\util\ObjectHelper;
use lflow\model\ProcessModel;

/**
 * 抽象节点解析类 完成通用的属性、变迁解析
 *
 * @author Mr.April
 * @since  1.0
 */
abstract class AbstractNodeParser implements NodeParser
{

    /**
     * 模型对象
     *
     * @var \lflow\ckpt\NodeCkpt
     */
    protected NodeCkpt $ckpt;

    /**
     * 实现NodeParser接口的parse函数
     * 由子类产生各自的模型对象，设置常用的名称属性，并且解析子节点transition，构造TransitionModel模型对象
     */
    public function parse(ProcessModel $model, null|object|array $nodes): void
    {
        $processE   = json_decode(json_encode($model->getData('content')));
        $properties = (object)$nodes->properties ?? (object)[];
        $this->ckpt = $this->newCkpt();
        $this->ckpt->setName($nodes->{NodeParser::ATTR_NAME} ?? '');
        $this->ckpt->setDisplayName($nodes->text->value ?? '');

        $this->ckpt->setPreInterceptors(ObjectHelper::getObjectValue($properties, NodeParser::ATTR_PREINTERCEPTORS));
        $this->ckpt->setPostInterceptors(ObjectHelper::getObjectValue($properties, NodeParser::ATTR_POSTINTERCEPTORS));
//        $this->ckpt->setPreInterceptors('lflow/impl\LogInterceptor,lflow/impl\LogInterceptor');
//        $this->ckpt->setPostInterceptors('lflow/impl\LogInterceptor,lflow/impl\LogInterceptor');

        $edgesList = ObjectHelper::getObjectValue($processE, 'edges') ?? (object)[];
        foreach ($edgesList as $edges) {
            if (ObjectHelper::getObjectValue($nodes, NodeParser::ATTR_NAME) === ObjectHelper::getObjectValue($edges, NodeParser::EDGES_SOURCENODEID)) {
                $transition = new TransitionCkpt();
                $transition->setName(ObjectHelper::getObjectValue($edges, NodeParser::ATTR_NAME));
                $transition->setDisplayName($edges->text->value ?? '');
                $transition->setTo(ObjectHelper::getObjectValue($edges, NodeParser::EDGES_TARGETNODEID));
                $properties = (object)ObjectHelper::getObjectValue($edges, 'properties') ?? (object)[];
                $transition->setExpr(ObjectHelper::getObjectValue($properties, NodeParser::ATTR_EXPR));
                $transition->setSource($this->ckpt);
                $outputList   = $this->ckpt->getOutputs();
                $outputList[] = $transition;
                $this->ckpt->setOutputs($outputList);
                $this->parseNode($this->ckpt, $nodes);
            }
        }

    }

    /**
     * 子类可覆盖此方法，完成特定的解析
     *
     * @param \lflow\ckpt\NodeCkpt $ckpt
     * @param object|null          $nodes
     */
    protected function parseNode(NodeCkpt $ckpt, ?object $nodes): void
    {
    }

    /**
     * 抽象方法，由子类产生各自的模型对象
     *
     * @return \lflow\ckpt\NodeCkpt
     */
    protected abstract function newCkpt(): NodeCkpt;

    /**
     * 返回模型对象
     *
     * @return \lflow\ckpt\NodeCkpt
     */
    public function getCkpt(): NodeCkpt
    {
        return $this->ckpt;
    }
}
